#!/usr/bin/perl

package MediaWiki::API;
use strict;
use XML::Simple;
use HTTP::Cookies;
use LWP::UserAgent;
use HTTP::Request::Common;
use Data::Dumper;

# initialize http and xml
my $browser = new LWP::UserAgent;
my $xml = new XML::Simple;

sub new {
	my($type,$api,$verbose) = @_;
	my $self = {
		username => undef,
		password => undef,
		api => $api,
		verbose => $verbose,
		ua => new LWP::UserAgent,
		editToken => 0,
		isLoggedIn => 0,
	};
	my $cookie_jar = new HTTP::Cookies;
	$self->{ua}->cookie_jar($cookie_jar);
	bless($self, $type);
	return $self;
}
sub uploadFile {
	my ($self,$filename,$file) = @_;
	if ( !$self->{editToken} ) {
		$self->getEditToken();
	}
	my $request = POST $self->{root}.'api.php',
	Content_Type=>'multipart/form-data',
	Content=>[
		action => 'upload',
		filename => $filename,
		token => $self->{editToken},
		format => 'xml',
	];
		
	my $page = $browser->request($request);
	if ( $page->is_success ) {
		$self->verbose("Successfully uploaded file ${filename}.");
		print $page->content."\n";
		return 1;
	} else {
		$self->verbose("Error when attempting to upload file ${filename}. $page->{error}->{code}");
		return 0;
	}
}
sub writePage {
	my ($self,$title,$summary,$text,$section) = @_;
	if ( !$self->{editToken} ) {
		$self->getEditToken();
	}
	my ($request);
	if ( $section ) {
		$request = POST $self->{root}.'api.php',[action=>'edit',title=>$title,summary=>$summary,section=>$section,text=>$text,token=>$self->{editToken},format=>'xml'];
	} else {
		$request = POST $self->{root}.'api.php',[action=>'edit',title=>$title,summary=>$summary,text=>$text,token=>$self->{editToken},format=>'xml'];
	}
	my $page = $browser->request($request);
	if ( $page->is_success ) {
		my $data = $xml->XMLin($self->trim($page->content));
		if ( $data->{edit}->{result} eq "Success" ) {
			# Successfully wrote page
			$self->verbose("Successfully wrote page ${title}.");
			return ($data->{edit}->{pageid},$data->{edit}->{title},$data->{edit}->{oldrevid},$data->{edit}->{newrevid});
		} else {
			$self->verbose("Error when attempting to write page ${title}: $data->{error}->{code}");
			return 0;
		}
	} else { 
		$self->verbose("Error when connecting to ".$self->{host}.": ".$page->status_line."\n");
		return 0;
	}
}

sub getEditToken {
	my ($self) = @_;
	my $request = POST $self->{root}.'api.php',[action=>'query',prop=>'info',intoken=>'edit',titles=>'Main Page',format=>'xml'];
	$self->verbose("Attemping to get an edit token for this session.");
	my $page = $browser->request($request);
	if ( $page->is_success ) {
		my $data = $xml->XMLin($self->trim($page->content));
		$self->verbose("Got edit token: ".$data->{query}->{pages}->{page}->{edittoken});
		$self->{editToken} = $data->{query}->{pages}->{page}->{edittoken};
		return $self->{edittoken};
	} else {
		$self->verbose("Error when connecting to ".$self->{host}.": ".$page->status_line."\n");
		return 0;
	}
}

sub trim($)
{
	my $self = shift;
	my $string = shift;
	$string =~ s/^\s+//;
	$string =~ s/\s+$//;
	return $string;
}

sub loggedIn {
	my $self = shift;
	return $self->{isLoggedIn};
}

sub verbose {
	my ($self,$output) = @_;
	if ( $self->{verbose} ) {
		print $output . "\n";
	}
}
sub query {
	my ($self,$request);
	my $http = POST $self->{root}.'api.php',$request;
	my $page = $browser->request($request);
	if ( $page->is_success ) {
		return $xml->XMLin($self->trim($page->content));
	} else {
		return 0;
	}	

}
sub login {
	my ($self,$token) = @_;
	my ($request);
	if ( $token ) {
		$request = POST $self->{root}.'api.php',[action=>'login',lgname=>$self->{username},lgpassword=>$self->{password},lgtoken=>$token,format=>'xml'];
	} else {
		$request = POST $self->{root}.'api.php',[action=>'login',lgname=>$self->{username},lgpassword=>$self->{password},format=>'xml'];
	}
	$self->verbose("Attempting to login as $self->{username} on $self->{root}" .($token ? " with token $token" : "").".");	
	my $page = $browser->request($request);
	if ( $page->is_success ) {
		# Check if page successfully loaded
		my $data = $xml->XMLin($self->trim($page->content));
		if ( $data->{login}->{result} eq "NeedToken" ) {
			# MediaWiki Challenge for Authentication Token
			my $token = $data->{login}->{token};#Obtain challenge token... try again
			$self->verbose("Obtained authentication token: $token");
			return $self->login($token);
		} elsif ( $data->{login}->{result} eq "Success" ) {
			$self->verbose("Logged in successfully.");
			$self->{isLoggedIn} = 1;
			return (1,$data->{login}->{result});
		} else {
			$self->verbose("Login failed: " . $data->{login}->{result});
			return (0,$data->{login}->{result});
		}
	} else {
		# Some page error (404,403?)
		$self->verbose("Error when connecting to ".$self->{host}.": ".$page->status_line."\n");
		return (0,$page->status_line);
	}
}
